package jsonrpcclient

import (
	"code.google.com/p/jesus-1496/serverlog"
	"code.google.com/p/jesus-1496/settings"
	"code.google.com/p/jesus-1496/utils/env"
	"fmt"
	"io"
	"net/rpc/jsonrpc"
	"os"
	"os/exec"
	"path"
)

var logger = serverlog.NewServerLog("jsonrpcclient")

//This can be used to panic after a write to stderr. Good to stop server starting
// if remote server cannot be started. May need to move this to the utils if
// it proves to be useful elsewhere
type panicAfterStdErr struct {
	stderr       io.Writer
	panicMessage string
}

func (s *panicAfterStdErr) Write(p []byte) (int, error) {
	defer panic(s.panicMessage)
	return s.stderr.Write(p)
}

func NewPanicAfterStdErr(panicMessage string) *panicAfterStdErr {
	return &panicAfterStdErr{os.Stderr, panicMessage}
}

func startServer(ip, port string) {
	rpcCmd := exec.Command("python", path.Join(env.GetProjectDir(), "python", "jsonrpcserver.py"), ip, port)
	rpcCmd.Stderr = NewPanicAfterStdErr("Error with python rpc server. See stderr for details.")
	rpcCmd.Stdout = os.Stdout
	logger.Printf("Starting rpc server...")
	err := rpcCmd.Start()
	if err != nil {
		panic(err.Error())
	}
}

//Wraps the jsonrpc function to dial and close the client to stop the error messages
//being shown.
func Call(serviceMethod string, args interface{}, reply interface{}) error {
	client, err := jsonrpc.Dial("tcp", fmt.Sprintf("%s:%d", settings.Settings.Rpc.Ip, settings.Settings.Rpc.Port))
	if err != nil {
		return err
	}
	err = client.Call(serviceMethod, args, reply)
	client.Close()
	if err != nil {
		return err
	}
	return nil
}

func init() {
	startServer(settings.Settings.Rpc.Ip, fmt.Sprintf("%v", settings.Settings.Rpc.Port))
}
